/*
 * @Author:
 * @Date: 2023-03-20 19:27:47
 * @LastEditors: xxx
 * @LastEditTime: 2023-08-16 09:15:39
 * @FilePath: \hart\hart\hart_slave.c
 * @Description:
 * email:
 * Copyright (c) 2023 by xxx, All Rights Reserved.
 */

#include "../inc/hart_slave.h"
#include "../inc/hart_slave_frame.h"
static hart_slave_init_t *handle;

// 内部状态检查
static response_communication_code_e hart_slave_state_check(uint8_t command)
{
    // 检查是否自检过程中
    if (TRUE == hart_device_attribute.device_status.busy)
    {
        return RESPONSE_COMMUNICATION_CODE_32;
    }

    //  检查是否开启的写保护
    if (hart_is_write_command(command))
    {
        if (WRITE_PROTECT_CODE_WRITE_PROTECT == hart_device_attribute.flash_variable.write_protect_code)
        {
            return RESPONSE_COMMUNICATION_CODE_7;
        }
    }

    // 检查是否锁定
    if (hart_is_write_command(command))
    {
        if (LOCK_DEVICE_CODE_0 != hart_device_attribute.flash_variable.lock_code)
        {
            return RESPONSE_COMMUNICATION_CODE_16;
        }
    }
    return RESPONSE_COMMUNICATION_CODE_0;
}

static BOOL hart_slave_command_check(uint32_t command, hart_command_req_t *req)
{
#ifdef STM32
    uint16_t command_index = 0;
    switch (command)
    {
    case 0:
        command_index = HART_COMMAND_0;
        break;
    case 1:
        command_index = HART_COMMAND_1;
        break;
    case 2:
        command_index = HART_COMMAND_2;
        break;
    case 3:
        command_index = HART_COMMAND_3;
        break;
    case 6:
        command_index = HART_COMMAND_6;
        break;
    case 8:
        command_index = HART_COMMAND_8;
        break;
    case 12:
        command_index = HART_COMMAND_12;
        break;
    case 13:
        command_index = HART_COMMAND_13;
        break;
    case 15:
        command_index = HART_COMMAND_15;
        break;
    case 17:
        command_index = HART_COMMAND_17;
        break;
    case 18:
        command_index = HART_COMMAND_18;
        break;
    case 20:
        command_index = HART_COMMAND_20;
        break;
    case 21:
        command_index = HART_COMMAND_21;
        break;
    case 22:
        command_index = HART_COMMAND_22;
        break;
    case 38:
        command_index = HART_COMMAND_38;
        break;
    case 48:
        command_index = HART_COMMAND_48;
        break;
    case 33:
        command_index = HART_COMMAND_33;
        break;
    case 39:
        command_index = HART_COMMAND_39;
        break;
    case 41:
        command_index = HART_COMMAND_41;
        break;
    case 42:
        command_index = HART_COMMAND_42;
        break;
    case 71:
        command_index = HART_COMMAND_71;
        break;
    case 79:
        command_index = HART_COMMAND_79;
        break;
    case 89:
        command_index = HART_COMMAND_89;
        break;
    case 90:
        command_index = HART_COMMAND_90;
        break;
    case 512:
        command_index = HART_COMMAND_512;
        break;
    case 513:
        command_index = HART_COMMAND_513;
        break;
    case 516:
        command_index = HART_COMMAND_516;
        break;
    case 517:
        command_index = HART_COMMAND_517;
        break;
    case 518:
        command_index = HART_COMMAND_518;
        break;
    case 519:
        command_index = HART_COMMAND_519;
        break;
    case 130:
        command_index = HART_COMMAND_130;
        break;
    case 131:
        command_index = HART_COMMAND_131;
        break;
    case 132:
        command_index = HART_COMMAND_132;
        break;
    case 133:
        command_index = HART_COMMAND_133;
        break;
    case 140:
        command_index = HART_COMMAND_140;
        break;
    case 141:
        command_index = HART_COMMAND_141;
        break;
    case 254:
        command_index = HART_COMMAND_254;
        break;
    case 255:
        command_index = HART_COMMAND_255;
        break;
    case 256:
        command_index = HART_COMMAND_256;
        break;
    case 257:
        command_index = HART_COMMAND_257;
        break;
    case 258:
        command_index = HART_COMMAND_258;
        break;
    case 259:
        command_index = HART_COMMAND_259;
        break;
    case 260:
        command_index = HART_COMMAND_260;
        break;
    case 261:
        command_index = HART_COMMAND_261;
        break;
    case 500:
        command_index = HART_COMMAND_500;
        break;
    case 501:
        command_index = HART_COMMAND_501;
        break;
    case 534:
        command_index = HART_COMMAND_534;
        break;
    default:
        return FALSE;
    }
    return hart_command_ptr_arr[command_index](req, handle->response); // 执行命令
#else
    if (hart_command_ptr_arr[command] == FALSE)
    {
        return FALSE;
    }
    return hart_command_ptr_arr[command](req, handle->response); // 执行命令
#endif
}

/**
 * @brief hart从机处理函数
 * @param {uint8_t} *rxBuf: 接收到的数据
 * @param {uint16_t} len: 接收到的数据长度
 * @return: TRUE: 处理成功
 *          FALSE: 处理失败
 */
BOOL hart_slave_handle(uint8_t uart_index, uint8_t *rxBuf, uint16_t len)
{
    if (!DBG_ASSERT(rxBuf != NULL __DBG_LINE))
        return FALSE;
    if (!DBG_ASSERT(len != 0 __DBG_LINE))
        return FALSE;

    uint8_t rsp_len = 0; // 响应数据长度
    uint16_t offset = 0;
    uint8_t address_length = 0, command_length = 0;
    hart_short_address_u poll_address;
    hart_long_address_u long_address;
    uint8_t *origin_address = NULL;
    hart_command_req_t req;
    hart_delimiter_u delimiter;
    uint32_t command = 0;
    BOOL ret = FALSE;

    hart_device_attribute.message_count.stx++;
    delimiter.data = 0;
    osel_memset((uint8_t *)&poll_address, 0, sizeof(hart_short_address_u));
    osel_memset((uint8_t *)&long_address, 0, sizeof(hart_long_address_u));

    handle->response->code = RESPONSE_COMMUNICATION_CODE_0;
    handle->response->data_length = 0;
    handle->response->data_p = handle->response->data;
    osel_memset((uint8_t *)handle->response->data, 0, HART_RESPONSE_MAX_LEN);
    osel_memset((uint8_t *)&req, 0, sizeof(hart_command_req_t));

    // 判断是否来自主机的请求
    hart_delimiter_u *delimiter_p = (hart_delimiter_u *)&rxBuf[offset];
    if (delimiter_p->bits.frame_type != HART_STX_FRAME)
    {
        return FALSE;
    }
    req.delimiter_type = delimiter_p->bits.addr_type;
    offset++;

    get_address(req.delimiter_type, req.address, &address_length); // 获取本机的地址
    // 比较主机请求的地址和本地地址是否一致
    if (delimiter_p->bits.addr_type == HART_DELIMITER_TYPE_SHORT)
    {
        poll_address.data = rxBuf[offset];
        uint8_t tmp = poll_address.bits.slave;
        origin_address = &tmp;
        if (*origin_address != req.address[0])
        {
            return FALSE;
        }
        req.master = poll_address.bits.master;
    }
    else
    {
        osel_memcpy((uint8_t *)&long_address.data, &rxBuf[offset], sizeof(uint40_t));
        uint8_t tmp[HART_LONG_ADDRESS_LEN];
        osel_memset(tmp, 0, HART_LONG_ADDRESS_LEN);
        tmp[0] = long_address.bits.reserved;
        osel_memcpy(&tmp[1], (uint8_t *)&long_address.bits.slave, 4);
        origin_address = tmp;

        // 比较两个地址是否相等
        if (osel_memcmp(origin_address, req.address, HART_LONG_ADDRESS_LEN) != 0)
        {
            return FALSE;
        }
        req.master = long_address.bits.master;
    }
    offset += address_length;

    // 根据界定符中的扩展字节数量来确定命令码
    command_length = delimiter_p->bits.ext_bytes + 1;
    osel_memcpy((uint8_t *)&req.command, &rxBuf[offset], command_length);
    switch (command_length)
    {
    case 1: // 1个字节
        command = req.command;
        break;
    case 2: // 2个字节
        command = B2S_UINT16(req.command);
        break;
    default:
        return FALSE;
    }
    offset += command_length;

    req.data_length = rxBuf[offset++]; // TODO 数据长度判断

    osel_memcpy((uint8_t *)&req.data, &rxBuf[offset], req.data_length); // 根据数据长度复制数据
    offset += req.data_length;

    delimiter.bits.frame_type = HART_ACK_FRAME; // 应答帧
    delimiter.bits.addr_type = req.delimiter_type;
    delimiter.bits.ext_bytes = delimiter_p->bits.ext_bytes;
    // 填充缓存数据结构
    handle->response->cache_data.delimiter.data = delimiter.data;
    osel_memcpy((uint8_t *)&handle->response->cache_data.command, (uint8_t *)&req.command, command_length);
    handle->response->cache_data.command_length = command_length;
    handle->response->cache_data.address_length = address_length;

    // 填充地址
    if (req.delimiter_type == HART_DELIMITER_TYPE_SHORT)
    {
        handle->response->cache_data.address[0] = poll_address.data;
    }
    else
    {
        osel_memcpy(handle->response->cache_data.address, (uint8_t *)&long_address.data, HART_LONG_ADDRESS_LEN); // 长地址5个字节
    }

    handle->response->code = hart_slave_state_check(command); // 内部状态检查

    if (RESPONSE_COMMUNICATION_CODE_0 == handle->response->code)
    {
        // LOG_PRINT("%d", command);
        ret = hart_slave_command_check(command, &req);

        if (ret == FALSE)
        {
            if (handle->response->code == RESPONSE_COMMUNICATION_CODE_127)
            {
                // 需要将回复的消息缓存起来，等待下次发送,UUID在每个处理指令的函数中赋值
                rsp_len = handle->response->data_p - handle->response->data;
                handle->response->cache_data.payload_length = rsp_len;
                if (rsp_len != 0)
                {
                    handle->response->data_p = handle->response->data;
                    handle->response->cache_data.payload = osel_mem_alloc(rsp_len);
                    osel_memcpy(handle->response->cache_data.payload, handle->response->data, rsp_len);
                }
                handle->response->cache_data.code = RESPONSE_COMMUNICATION_CODE_0;
                handle->response->cache_data.uart_index = uart_index;
                hart_cache_add(handle->response->cache_data);
            }
            return FALSE;
        }
    }
    rsp_len = handle->response->data_p - handle->response->data;
    handle->response->cache_data.payload_length = rsp_len;

    if (rsp_len != 0)
    {
        handle->response->data_p = handle->response->data;
        handle->response->cache_data.payload = osel_mem_alloc(rsp_len);
        osel_memcpy(handle->response->cache_data.payload, handle->response->data, rsp_len);
    }
    handle->response->cache_data.code = handle->response->code;
    handle->response->cache_data.uart_index = uart_index;
    hart_slave_device_send(&handle->response->cache_data);
    return TRUE;
}

/**
 * @brief 从机初始化
 * @return {*}
 */
BOOL hart_slave_init(const hart_slave_init_t *const init)
{
    if (!DBG_ASSERT(init != NULL __DBG_LINE))
        return FALSE;
    handle = (hart_slave_init_t *)init;
    handle->response->code = RESPONSE_COMMUNICATION_CODE_0;
    hart_slave_req_init(); // 从机请求初始化

    return TRUE;
}

/**
 * @brief 发送响应帧给一个HART从设备
 * @param {hart_cache_t} *cache_data：缓存数据指针
 * @return {*}
 * @note 该函数用于向HART从设备发送响应帧。
 */
void hart_slave_device_send(hart_cache_t *cache_data)
{
    uint8_t rsp_len = 0;        // 响应数据长度
    uint8_t xor = 0;            // 异或校验
    uint8_t *data_len_p = NULL; // 数据长度指针
    uint8_t *response_code_p = NULL;
    uint8_t preamble_def = HART_PREAMBLE_DEFAULT_LEN; // 引导码长度
    DBG_ASSERT(cache_data != NULL __DBG_LINE);
    if (cache_data->payload_length > 0)
    {
        handle->response->data_p = handle->response->data;
    }

    // 填充回复数据
    // 填充引导码
    for (uint8_t i = 0; i < preamble_def; i++)
    {
        *handle->response->data_p++ = HART_PREAMBLE;
    }
    // 填充界定符
    *handle->response->data_p++ = cache_data->delimiter.data;
    // 填充地址
    osel_memcpy(handle->response->data_p, (uint8_t *)&cache_data->address, cache_data->address_length); // 长地址5个字节
    handle->response->data_p += cache_data->address_length;
    // 填充命令
    osel_memcpy(handle->response->data_p, (uint8_t *)&cache_data->command, cache_data->command_length);
    handle->response->data_p += cache_data->command_length;

    data_len_p = handle->response->data_p;
    hart_frame_data_length_start(&data_len_p);
    handle->response->data_p++;
    response_code_p = handle->response->data_p;
    hart_frame_response_code_start(&response_code_p);
    handle->response->data_p += 2;

    // 填充载荷
    if (cache_data->payload_length != 0)
    {
        osel_memcpy(handle->response->data_p, cache_data->payload, cache_data->payload_length);
        handle->response->data_p += cache_data->payload_length;
        osel_mem_free(cache_data->payload);
    }

    hart_frame_data_length_end(handle->response->data_p);
    hart_frame_response_communication_code(cache_data->code);
    hart_frame_slave_response_operate_code(&hart_device_attribute);

    // 填充校验码
    rsp_len = handle->response->data_p - handle->response->data;
    xor = xor_compute(&handle->response->data[preamble_def], (rsp_len - preamble_def)); // 除前导码和校验字节外所有字节的异或之后
    *handle->response->data_p++ = xor;
    rsp_len++;
    handle->response->data_length = rsp_len;

    if (handle->response->data_length > 0)
    {
        handle->response_call(cache_data->uart_index, handle->response->data, handle->response->data_length);
        hart_device_attribute.message_count.ack++;
    }
}

/**
 * @brief 从机设备属性初始化
 * @return {*}
 */
void hart_slave_device_attribute_init(void)
{
    // 锁定状态
    if (LOCK_DEVICE_CODE_1 == hart_device_attribute.flash_variable.lock_code)
    {
        hart_device_attribute.flash_variable.lock_code = LOCK_DEVICE_CODE_0;
    }

    // 设置rtc标志
    if (hart_device_attribute.flash_variable.real_time_clock.rtc_flags == 0 &&
        hart_device_attribute.flash_variable.real_time_clock.time == 0)
    {
        hart_device_attribute.flash_variable.real_time_clock.rtc_flags = REAL_TIME_CLOCK_FLAGS_2;
    }
    else
    {
        hart_device_attribute.flash_variable.real_time_clock.rtc_flags = REAL_TIME_CLOCK_FLAGS_1;
    }

    // 设备状态
    osel_memset((uint8_t *)&hart_device_attribute.device_status, 0, sizeof(hart_device_status_t));
    hart_device_attribute.device_status.operational_state = DEVICE_OPERATIONAL_STATE_0;
    hart_device_attribute.device_status.additional_device_status.extended_device_status = EXTENDED_DEVICE_STATUS_0;
    hart_device_attribute.device_status.additional_device_status.device_operating_mode = OPERATING_MODE_CODES_0;
    hart_device_attribute.device_status.additional_device_status.standardized_status0 = STANDARDIZED_STATUS0_2;
    hart_device_attribute.device_status.additional_device_status.standardized_status1 = STANDARDIZED_STATUS1_3;
    hart_device_attribute.device_status.additional_device_status.analog_channel_saturated = ANALOG_CHANNEL_SATURATED_1;
    hart_device_attribute.device_status.additional_device_status.standardized_status2 = STANDARDIZED_STATUS2_0;
    hart_device_attribute.device_status.additional_device_status.standardized_status3 = STANDARDIZED_STATUS3_5;
    hart_device_attribute.device_status.additional_device_status.analog_channel_fixed = ANALOG_CHANNEL_FIXED_1;
    hart_additional_device_status_crc_init();
}

void hart_slave_device_attribute_user_init(void)
{
    osel_memset((uint8_t *)&hart_device_attribute.flash_variable_user, 0, sizeof(hart_storage_variable_user_t));
}
